/*		Filename: 	logical_server.cpp
 *		Author:		彭望
 *		Date:		2012-01-12
 *		Use:		实现逻辑业务服务器端的结构
 */
#include "logical_server.h"

CLogicalServer::CLogicalServer(const string& strConfigFilename)
		:logger(Logger::getLogger())
{
	this->loadConfig( strConfigFilename );
	this->init();
}
CLogicalServer::CManagerPtr CLogicalServer::GetManager(ManagerType key)
{
	return m_managers[key];
}

CSessionPtr CLogicalServer::make_session(const CLogicalServer& s)
{
		return CSessionPtr( new CSession(s) );
}

RetCode_t CLogicalServer::loadConfig(const string& strConfigFilename)
{
	using namespace libconfig;
	Config config;
	try{
			config.readFile( strConfigFilename.c_str() );
	}catch(ParseException e)
	{
			logger.error("Cannot parse config from %s!", strConfigFilename.c_str());
			goto err;
	}catch(FileIOException e)
	{
			logger.error("Cannot open config file %s!", strConfigFilename.c_str() );
			goto err;
	}
	unsigned int port;
	if( !config.lookupValue("SERVER_LISTEN_PORT", port) || (port > 65535 || port < 1025) )
	{
			m_listenPort = 9026;
			logger.warn("INVALID SERVER_LISTEN_PORT, use default %d!", m_listenPort );
	}else{
			m_listenPort = port;
	}

	unsigned int clientPort;
	if( !config.lookupValue("CLIENT_PORT", clientPort) || (port > 65535 || port < 1025) )
	{
		m_clientPort = 9028;
		logger.warn("INVALID CLIENT_PORT, use default %d!", m_clientPort);
	}else{
			m_clientPort = clientPort;
	}

	if( !config.lookupValue("DB_CONFIG_NAME", m_dbConfigName) )
	{
			logger.warn("no DB_CONFIG_NAME specified in %s, use defaule!", strConfigFilename.c_str());
			m_dbConfigName = "database.conf";
	}

		return RET_OK;
err:
		return RET_INVALID_ARG;
}

//初始化程序各个组件(监听端口等)
RetCode_t CLogicalServer::init()
{
	DBManagerPtr dbPtr( new CDatabaseManager(m_dbConfigName) );
	m_managers[DB_MANAGER] = dbPtr;

	CCardManagerPtr cardManagerPtr( new CCardManager(dbPtr) );
	m_managers[CARD_MANAGER] = cardManagerPtr;

	CFeeManagerPtr fmPtr( new CFeeManager(cardManagerPtr) );
	m_managers[FEE_MANAGER] = fmPtr;

	//整个周期内只调用一次,不存在泄漏问题
	io_service* p = new io_service();

	CNetManagerPtr nmPtr( new CNetManager(*p) );
	nmPtr->init();
	m_managers[NET_MANAGER] = nmPtr;
	return RET_OK;
}

RetCode_t CLogicalServer::listen()
{
		CNetManagerPtr nmPtr = boost::any_cast<CNetManagerPtr>(m_managers[NET_MANAGER]);
		
		CNetManager::server_callback_func_t func = bind(&CLogicalServer::listen_callback, this, _1,_2,_3);
		logger.debug("port : %u", m_listenPort);
		nmPtr->async_server_listen("127.0.0.1", m_listenPort, func);
		return RET_OK;
}

void CLogicalServer::listen_callback(const SessionIndex_t& index, istream& is, ostream& os)
{
		BOOST_AUTO(iter, m_sessions.find(index) );
		if( iter == m_sessions.end() )
		{
			CSessionPtr session = CLogicalServer::make_session(*this);			
			m_sessions[index] = session;
		}
		m_sessions[index]->process(is, os);
}
